package com.union.vehicleassistant.util;

import static android.content.Context.LOCATION_SERVICE;

import android.Manifest;
import android.app.Activity;
import android.bluetooth.BluetoothGatt;
import android.bluetooth.BluetoothGattCharacteristic;
import android.bluetooth.BluetoothGattService;
import android.content.Context;
import android.content.Intent;
import android.location.LocationManager;
import android.os.Build;
import android.provider.Settings;

import androidx.annotation.NonNull;

import com.blankj.utilcode.util.LogUtils;
import com.clj.fastble.BleManager;
import com.clj.fastble.callback.BleGattCallback;
import com.clj.fastble.callback.BleNotifyCallback;
import com.clj.fastble.callback.BleScanCallback;
import com.clj.fastble.callback.BleWriteCallback;
import com.clj.fastble.data.BleDevice;
import com.clj.fastble.exception.BleException;
import com.clj.fastble.scan.BleScanRuleConfig;
import com.clj.fastble.utils.HexUtil;
import com.hjq.base.BaseDialog;
import com.hjq.permissions.XXPermissions;
import com.union.vehicleassistant.R;
import com.union.vehicleassistant.widget.dialog.MessageDialog;

import java.nio.charset.Charset;
import java.util.ArrayList;
import java.util.List;
import java.util.UUID;

public class BlueToothUtil {

    private static BluetoothGattService communicateService; // 可用于通讯的服务
    private static BleDevice availableDevice; // 可用于通讯的服务设备

    /**
     * 请求权限
     *
     * @param activity
     * @param callback
     */
    public static void initPermission(Activity activity, onPermissionGrantedCallback callback) {
        List<String> mPermissionList = getPermissions();
        boolean supportBle = BleManager.getInstance().isSupportBle();
        if (!supportBle) {
            callback.onUnSupport();
        } else {
            boolean b = enableGps(activity);
            if (b) {
                XXPermissions.with(activity)
                        .permission(mPermissionList)
                        .request((permissions, all) -> callback.onPermissionGranted(all));
            }
        }

    }

    @NonNull
    private static List<String> getPermissions() {
        List<String> mPermissionList = new ArrayList<>();
        mPermissionList.add(Manifest.permission.ACCESS_COARSE_LOCATION);
        mPermissionList.add(Manifest.permission.ACCESS_FINE_LOCATION);
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) {
            // Android 版本大于等于 Android12 时
            // 只包括蓝牙这部分的权限，其余的需要什么权限自己添加
            mPermissionList.add(Manifest.permission.BLUETOOTH_SCAN);
            mPermissionList.add(Manifest.permission.BLUETOOTH_ADVERTISE);
            mPermissionList.add(Manifest.permission.BLUETOOTH_CONNECT);
        }
        return mPermissionList;
    }

    /**
     * 判断是否开启gps定位
     *
     * @return
     */
    private static boolean enableGps(Context context) {
        LocationManager manager = (LocationManager) context.getSystemService(LOCATION_SERVICE);
        boolean isGps = false;
        if (manager != null) {
            isGps = manager.isProviderEnabled(LocationManager.GPS_PROVIDER);
        }

        LogUtils.d(isGps);

        if (!isGps) {
            new MessageDialog.Builder(context)
                    .setMessage(R.string.bluetooth_without_gps_permission)
                    .setListener(new MessageDialog.OnListener() {
                        @Override
                        public void onConfirm(BaseDialog dialog) {
                            Intent intent = new Intent();
                            intent.setAction(Settings.ACTION_LOCATION_SOURCE_SETTINGS);
                            context.startActivity(intent);
                        }

                        @Override
                        public void onCancel(BaseDialog dialog) {
                            MessageDialog.OnListener.super.onCancel(dialog);
                        }
                    }).show();
        }

        return isGps;
    }

    /**
     * 通过Mac地址，获取已连接蓝牙设备
     *
     * @param mac 蓝牙Mac地址
     * @return 返回蓝牙设备 {@link BleDevice}
     */
    public static BleDevice getBleDevice(String mac) {
        List<BleDevice> bleDevices = BleManager.getInstance().getAllConnectedDevice();
        for (BleDevice device : bleDevices) {
            if (device.getMac().equals(mac)) {
                return device;
            }
        }
        return null;
    }


    /**
     * 扫描蓝牙设备
     *
     * @param listener 自定义扫描监听
     * @param <T>      继承{@link BlueToothStateChangeListener}
     */
    public static <T extends BlueToothStateChangeListener> void scanBlueTooth(T listener) {
        BleScanRuleConfig scanRuleConfig = new BleScanRuleConfig.Builder()
                .setDeviceName(true, "Air")
                .setAutoConnect(true)      // 连接时的autoConnect参数，可选，默认false
                .setScanTimeOut(15000)     // 扫描超时时间，可选，默认10秒
                .build();
        BleManager.getInstance().initScanRule(scanRuleConfig);

        BleManager.getInstance().scan(new BleScanCallback() {
            @Override
            public void onScanFinished(List<BleDevice> scanResultList) {
                if (listener != null) {
                    listener.onScanFinish(scanResultList);
                }
            }

            @Override
            public void onScanStarted(boolean success) {

            }

            @Override
            public void onScanning(BleDevice bleDevice) {
                if (listener != null) {
                    listener.onScanning(bleDevice);
                }
            }
        });
    }

    /**
     * 链接设备
     *
     * @param deviceMac
     * @param listener
     */
    public static <T extends BlueToothStateChangeListener> void connectDevice(String deviceMac, T listener) {
        BleManager.getInstance().connect(deviceMac, new BleGattCallback() {
            @Override
            public void onStartConnect() {
                if (listener != null) {
                    listener.onDisConnect();
                }
            }

            @Override
            public void onConnectFail(BleDevice bleDevice, BleException exception) {
                if (listener != null) {
                    listener.onConnectFail();
                }
            }

            @Override
            public void onConnectSuccess(BleDevice bleDevice, BluetoothGatt gatt, int status) {
                if (null != listener)
                    listener.onConnectSuccess(bleDevice, gatt, status);
                registerReceiveCallback(bleDevice, gatt, listener);
            }

            @Override
            public void onDisConnected(boolean isActiveDisConnected, BleDevice device, BluetoothGatt gatt, int status) {
                if (null != listener)
                    listener.onDisConnect();
            }
        });
    }

    /**
     * 注册接收消息
     *
     * @param bleDevice
     * @param listener
     */
    public static <T extends BlueToothStateChangeListener> void registerReceiveCallback(BleDevice bleDevice, T listener) {
        BluetoothGatt gatt = BleManager.getInstance().getBluetoothGatt(bleDevice);
        registerReceiveCallback(bleDevice, gatt, listener);
    }

    /**
     * 注册接收消息
     *
     * @param bleDevice
     * @param bluetoothGatt
     * @param listener
     */
    public static <T extends BlueToothStateChangeListener> void registerReceiveCallback(BleDevice bleDevice, BluetoothGatt bluetoothGatt, T listener) {
        List<BluetoothGattService> services = bluetoothGatt.getServices();
        for (BluetoothGattService service : services) {
            for (BluetoothGattCharacteristic characteristic : service.getCharacteristics()) {
                UUID characteristicUuid = characteristic.getUuid();

                int properties = characteristic.getProperties();
                if ((properties & BluetoothGattCharacteristic.PROPERTY_NOTIFY) > 0) {
                    LogUtils.d("链接的特征值：", service.getUuid() + "",
                            properties,
                            characteristicUuid,
                            characteristic.getDescriptor(characteristicUuid));
                    openNotify(bleDevice, service, characteristicUuid, listener);
                }
            }
        }
    }

    /**
     * 开启消息通知
     *
     * @param bleDevice  蓝牙设备
     * @param service    可通讯的服务
     * @param uuidNotify 通知uuid
     * @param listener   监听器
     */
    private static <T extends BlueToothStateChangeListener> void openNotify(BleDevice bleDevice, BluetoothGattService service, UUID uuidNotify, T listener) {
        communicateService = service;
        availableDevice = bleDevice;
        BleManager.getInstance().notify(bleDevice, service.getUuid().toString(), uuidNotify.toString(), new BleNotifyCallback() {
            @Override
            public void onNotifySuccess() {
                LogUtils.d("open success");
                if (null != listener)
                    listener.onOpenNotify(service, uuidNotify.toString());
            }

            @Override
            public void onNotifyFailure(BleException e) {
                LogUtils.d("open onNotifyFailure");
                if (null != listener)
                    listener.onOpenNotifyFailure();
            }

            @Override
            public void onCharacteristicChanged(byte[] bytes) {
                String hexString = HexUtil.encodeHexStr(bytes);
                LogUtils.d("接收到的数据：", hexString,bytes.length);
                if (null != listener) {
                    listener.onReceiveCharacter(bytes);
                }
            }
        });
    }

    /**
     * 写数据：向蓝牙发送数据
     * 仅适用于 {@link BlueToothUtil} 内部使用发送数据
     *
     * @param data 发送的数据
     */
    private static void writeData(String data) {
        if (availableDevice == null) return;
        if (communicateService == null) return;
        SettingUtils.getInstance().setConnectBleMac(availableDevice.getMac());
        for (BluetoothGattCharacteristic characteristic : communicateService.getCharacteristics()) {
            int properties = characteristic.getProperties();
            if ((properties & BluetoothGattCharacteristic.PROPERTY_WRITE_NO_RESPONSE) > 0
                    || (properties & BluetoothGattCharacteristic.PROPERTY_WRITE) > 0) {

                LogUtils.d("蓝牙可写服务：", communicateService.getUuid(),
                        "蓝牙特性：", characteristic.getProperties(),
                        "蓝牙uuid:", characteristic.getUuid(),
                        "发送的数据", data, HexUtil.hexStringToBytes(data), new String(HexUtil.hexStringToBytes(data), Charset.defaultCharset()));

                writeBytes(availableDevice, communicateService.getUuid().toString(), characteristic.getUuid().toString(), data.getBytes(Charset.defaultCharset()));
            }
        }
    }


    /**
     * 写数据：向蓝牙发送数据
     *
     * @param device 蓝牙设备
     * @param gatt   BluetoothGatt
     * @param data   字节数组
     */
    public static void writeData(BleDevice device, BluetoothGatt gatt, byte[] data) {
        List<BluetoothGattService> services = gatt.getServices();
        for (BluetoothGattService service : services) {
            for (BluetoothGattCharacteristic characteristic : service.getCharacteristics()) {
                UUID characteristicUuid = characteristic.getUuid();

                int properties = characteristic.getProperties();
                if ((properties & BluetoothGattCharacteristic.PROPERTY_WRITE_NO_RESPONSE) > 0
                        || (properties & BluetoothGattCharacteristic.PROPERTY_WRITE) > 0) {
                    LogUtils.d("蓝牙可写服务：", service.getUuid(),
                            "蓝牙特性：", characteristic.getProperties(),
                            "蓝牙uuid:", characteristic.getUuid(),
                            "发送的数据", data, new String(data, Charset.defaultCharset()));
                    writeBytes(device, service.getUuid().toString(), characteristicUuid.toString(), data);
                }
            }
        }
    }

    public static void writeData(BleDevice device, BluetoothGatt gatt, String data) {
        writeData(device, gatt, data.getBytes(Charset.defaultCharset()));
    }


    public static void writeData(BleDevice bleDevice, String uuidService, String data) {
        writeData(bleDevice, uuidService, data.getBytes(Charset.defaultCharset()));
    }

    public static void writeData(BleDevice bleDevice, String uuidService, byte[] data) {
        BluetoothGatt gatt = BleManager.getInstance().getBluetoothGatt(bleDevice);
        List<BluetoothGattService> services = gatt.getServices();
        for (BluetoothGattService s : services) {
            if (s.getUuid().toString().equals(uuidService)) {
                for (BluetoothGattCharacteristic characteristic : s.getCharacteristics()) {
                    int properties = characteristic.getProperties();
                    if ((properties & BluetoothGattCharacteristic.PROPERTY_WRITE_NO_RESPONSE) > 0
                            || (properties & BluetoothGattCharacteristic.PROPERTY_WRITE) > 0) {
                        writeBytes(bleDevice, uuidService, characteristic.getUuid().toString(), data);
                    }
                }
            }
        }

    }

    private static void writeBytes(BleDevice bleDevice, String uuidService, String uuidWrite, byte[] b) {
        BleManager.getInstance().write(bleDevice, uuidService, uuidWrite, b, new BleWriteCallback() {
            @Override
            public void onWriteSuccess(int current, int total, byte[] justWrite) {
                LogUtils.e("写入成功", current, total, new String(justWrite, Charset.defaultCharset()));
            }

            @Override
            public void onWriteFailure(BleException e) {
                LogUtils.e("写入失败", e);
            }
        });
    }

    public interface onPermissionGrantedCallback {
        void onPermissionGranted(boolean b);

        void onUnSupport();
    }
}
